home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / gopher / Unix / gopher+1.2b4 / gopherd / serverutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-09  |  7.8 KB  |  347 lines

  1. /********************************************************************
  2.  * lindner
  3.  * 3.4
  4.  * 1993/04/10 06:07:40
  5.  * /home/mudhoney/GopherSrc/CVS/gopher+/gopherd/serverutil.c,v
  6.  * Exp
  7.  *
  8.  * Paul Lindner, University of Minnesota CIS.
  9.  *
  10.  * Copyright 1991, 1992 by the Regents of the University of Minnesota
  11.  * see the file "Copyright" in the distribution for conditions of use.
  12.  *********************************************************************
  13.  * MODULE: serverutil.c
  14.  * utilities for the server.
  15.  *********************************************************************
  16.  * Revision History:
  17.  * serverutil.c,v
  18.  * Revision 3.4  1993/04/10  06:07:40  lindner
  19.  * More debug msgs
  20.  *
  21.  * Revision 3.3  1993/04/09  15:12:09  lindner
  22.  * Better error checking on getpeername()
  23.  *
  24.  * Revision 3.2  1993/03/24  20:28:55  lindner
  25.  * Moved some code from gopherd.c and changed error message delivery
  26.  *
  27.  * Revision 3.1.1.1  1993/02/11  18:02:53  lindner
  28.  * Gopher+1.2beta release
  29.  *
  30.  * Revision 1.2  1993/02/09  22:16:24  lindner
  31.  * Mods for gopher+ error results.
  32.  *
  33.  * Revision 1.1  1992/12/10  23:13:27  lindner
  34.  * gopher 1.1 release
  35.  *
  36.  *
  37.  *********************************************************************/
  38.  
  39.  
  40.  
  41. #include "gopherd.h"
  42.  
  43. /*
  44.  * Gopher + error mechanism
  45.  *
  46.  * errclass is the type of error
  47.  * text is the first line of error text,
  48.  * moretext is a char array of yet more text to send
  49.  */
  50.  
  51. void
  52. GplusError(sockfd, errclass, text, moretext)
  53.   int errclass;
  54.   char *text;
  55.   char **moretext;
  56. {
  57.      char outputline[256];
  58.      int i;
  59.  
  60.      sprintf(outputline, "--1\r\n%d %s <%s>\r\n0%s\t\t\t\r\n", 
  61.          errclass, GDCgetAdmin(Config),
  62.          GDCgetAdminEmail(Config), text);
  63.  
  64.      if (writestring(sockfd, outputline)<0) {
  65.       LOGGopher(sockfd, "Client went away!");
  66.       exit(-1);
  67.      }
  68.  
  69.      if (moretext != NULL)
  70.       for (i=0; moretext[i] != NULL; i++) {
  71.            writestring(sockfd, moretext[i]);
  72.            writestring(sockfd, ".\r\n");
  73.       }
  74.  
  75.      writestring(sockfd, ".\r\n");
  76.  
  77.      LOGGopher(sockfd, text);
  78.  
  79.      close(sockfd);
  80.  
  81.      return;
  82. }
  83.  
  84.  
  85. /* 
  86.  * This routine cleans up an open file descriptor and sends out a bogus
  87.  * filename with the error message
  88.  */
  89.  
  90. void
  91. Abortoutput(sockfd, errmsg)
  92.   int sockfd;
  93.   char *errmsg;
  94. {
  95.      GplusError(sockfd, 1, errmsg, NULL);
  96.  
  97. }
  98.  
  99. /*
  100.  * only works if non-chroot really...
  101.  */
  102.  
  103. boolean
  104. Setuid_username(username)
  105.   char *username;
  106. {
  107.      struct passwd *pw;
  108.  
  109.      if (getuid() != 0)
  110.       return(FALSE);
  111.  
  112.      pw = getpwnam(username);
  113.      
  114.      if (!pw) {
  115.       if (DEBUG)
  116.            printf("Couldn't find user '%s'\n", username);
  117.  
  118.       return(FALSE);
  119.      }
  120.  
  121.      if (setegid(pw->pw_gid) < 0)
  122.       return(FALSE);
  123.  
  124.      if (seteuid(pw->pw_uid) < 0)
  125.       return(FALSE);
  126.  
  127.      if (DEBUG)
  128.       printf("Successfully changed user privs to '%s'\n", username);
  129.  
  130.      return(TRUE);
  131. }
  132.  
  133.  
  134.  
  135. /*
  136.  *
  137.  *  Code stolen and heavily hacked from nntp
  138.  *
  139.  * inet_netnames -- return the network, subnet, and host names of
  140.  * our peer process for the Internet domain.
  141.  *
  142.  *      Parameters:     "sock" is our socket
  143.  *                      "host_name"
  144.  *                      is filled in by this routine with the
  145.  *                      corresponding ASCII names of our peer.
  146.  *       
  147.  *                      if there doesn't exist a hostname in DNS etal,
  148.  *                      the IP# will be inserted for the host_name
  149.  *
  150.  *                      "ipnum" is filled in with the ascii IP#
  151.  *      Returns:        Nothing.
  152.  *      Side effects:   None.
  153.  */
  154.  
  155. void
  156. inet_netnames(sockfd, host_name, ipnum)
  157.   int  sockfd;
  158.   char *host_name;
  159.   char *ipnum;
  160. {
  161.      struct sockaddr_in      sa;
  162.      int                     length;
  163.      u_long                  net_addr;
  164.      struct hostent          *hp;
  165.  
  166.      length = sizeof(sa);
  167.      if (getpeername(sockfd, &sa, &length))
  168.       /** May fail if sockfd has been closed **/
  169.       return;
  170.  
  171.      strcpy(ipnum, inet_ntoa(sa.sin_addr));
  172.      strcpy(host_name, inet_ntoa(sa.sin_addr));
  173.  
  174.      hp = gethostbyaddr((char *) &sa.sin_addr,sizeof (sa.sin_addr), AF_INET);
  175.      
  176.      if (hp != NULL)
  177.       (void) strcpy(host_name, hp->h_name);
  178.  
  179. }
  180.  
  181.  
  182.  
  183.  
  184.  
  185. /*
  186.  * is_mail_from_line - Is this a legal unix mail "From " line?
  187.  *
  188.  * Given a line of input will check to see if it matches the standard
  189.  * unix mail "from " header format. Returns 0 if it does and <0 if not.
  190.  *
  191.  * 2 - Very strict, also checks that each field contains a legal value.
  192.  *
  193.  * Assumptions: Not having the definitive unix mailbox reference I have
  194.  * assumed that unix mailbox headers follow this format:
  195.  *
  196.  * From <person> <date> <garbage>
  197.  *
  198.  * Where <person> is the address of the sender, being an ordinary
  199.  * string with no white space imbedded in it, and <date> is the date of
  200.  * posting, in ctime(3C) format.
  201.  *
  202.  * This would, on the face of it, seem valid. I (Bernd) have yet to find a
  203.  * unix mailbox header which doesn't follow this format.
  204.  *
  205.  * From: Bernd Wechner (bernd@bhpcpd.kembla.oz.au)
  206.  * Obfuscated by: KFS (as usual)
  207.  */
  208.  
  209. #define MAX_FIELDS 10
  210.  
  211. static char legal_day[]         = "SunMonTueWedThuFriSat";
  212. static char legal_month[]       = "JanFebMarAprMayJunJulAugSepOctNovDec";
  213. static int  legal_numbers[]     = { 1, 31, 0, 23, 0, 59, 0, 60, 1969, 2199 };
  214.  
  215. int is_mail_from_line(line)
  216. char *line;     /* Line of text to be checked */
  217. {
  218.     char *fields[MAX_FIELDS];
  219.     char *sender_tail;
  220.     register char *lp, **fp;
  221.     register int n, i;
  222.  
  223.     if (strncmp(line, "From ", 5)) return -100;
  224.  
  225.     lp = line + 5;
  226.     /* sender day mon dd hh:mm:ss year */
  227.     for (n = 0, fp = fields; n < MAX_FIELDS; n++) {
  228.         while (*lp && *lp != '\n' && isascii(*lp) && isspace(*lp)) lp++;
  229.         if (*lp == '\0' || *lp == '\n') break;
  230.         *fp++ = lp;
  231.         while (*lp && isascii(*lp) && !isspace(*lp))
  232.             if (*lp++ == ':' && (n == 4 || n == 5)) break;
  233.         if (n == 0) sender_tail = lp;
  234.    }
  235.  
  236.     if (n < 8) return -200-n;
  237.  
  238.     fp = fields;
  239.  
  240.     if (n > 8 && !isdigit(fp[7][0])) fp[7] = fp[8]; /* ... TZ year */
  241.     if (n > 9 && !isdigit(fp[7][0])) fp[7] = fp[9]; /* ... TZ DST year */
  242.  
  243.     fp++;
  244.     for (i = 0; i < 21; i += 3)
  245.         if (strncmp(*fp, &legal_day[i], 3) == 0) break;
  246.     if (i == 21) return -1;
  247.  
  248.     fp++;
  249.     for (i = 0; i < 36; i += 3)
  250.         if (strncmp(*fp, &legal_month[i], 3) == 0) break;
  251.     if (i == 36) return -2;
  252.  
  253.     for (i = 0; i < 10; i += 2) {
  254.         lp = *++fp;
  255.         if (!isdigit(*lp)) return -20-i;
  256.         n = atoi(lp);
  257.         if (n < legal_numbers[i] || legal_numbers[i+1] < n) return -10-i;
  258.    }
  259.     return 0;
  260. }
  261.  
  262.  
  263.  
  264. /* 
  265.  * Return the basename of a filename string, i.e. everything
  266.  * after the last "/" character. 
  267.  */
  268.  
  269. char *mtm_basename(string)
  270.     char *string;
  271. {
  272.   static   char *buff;
  273.   buff = string + strlen(string); /* start at last char */
  274.   while (*buff != '/' && buff > string)
  275.       buff--;
  276.   return( (char *) (*buff == '/'? ++buff : buff));
  277. }
  278.  
  279.  
  280.  
  281. /*
  282.  * Cache timeout value.
  283.  *   If cache is less than secs seconds old, it's ok.
  284.  *   Otherwise, compare time of cache to dir and all files in dir and dir/.cap.
  285.  *   If cache is newest, it's ok, otherwise it must be rebuilt.
  286.  * 
  287.  * Not really great for big directories, but better in general for smaller
  288.  * directories..
  289.  */
  290.  
  291. boolean
  292. Cachetimedout(cache, secs, dir)
  293.   char *cache;
  294.   int secs;
  295.   char *dir;
  296. {
  297.      STATSTR       buf;
  298.      int           result;
  299.      time_t        now;
  300.  
  301.      result = rstat(cache, &buf);
  302.  
  303.      if (result != 0)
  304.       return(-1);
  305.  
  306.      time(&now);
  307.      
  308.      if (DEBUG) 
  309.       printf("Cache now: %d, cache file: %d", now,buf.st_mtime);
  310.      
  311.      if ( now < (buf.st_mtime + secs))
  312.       return(FALSE);
  313.      else
  314.       return(TRUE);
  315.  
  316. }
  317.  
  318. /*
  319.  * Returns true (1) for a directory
  320.  *         false (0) for a file
  321.  *         -1 for anything else
  322.  */
  323.  
  324. boolean
  325. isadir(path)
  326.   char *path;
  327. {
  328.      STATSTR buf;
  329.      int result;
  330.  
  331.      result = rstat(path, &buf);
  332.  
  333.      if (result != 0)
  334.       return(-1);
  335.      
  336.      if (S_ISDIR(buf.st_mode)) {
  337.       if (! access(path, F_OK))
  338.            return(1);
  339.       else
  340.            return(-1);
  341.      }
  342.      else if (S_ISREG(buf.st_mode))
  343.       return(0);
  344.      else
  345.       return(-1);
  346. }
  347.